home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / STRINGS / TPWRST / TPWRDSTR.PAS < prev   
Pascal/Delphi Source File  |  1990-03-28  |  20KB  |  685 lines

  1. {$S-,R-,V-,I-,B-,F+}
  2.  
  3. {$IFNDEF Ver40}
  4.   {$I OPLUS.INC}
  5. {$ENDIF}
  6.  
  7. {*********************************************************}
  8. {*                  TPWRDSTR.PAS 1.0                     *}
  9. {*          Copyright (c) Ken Henderson 1990.            *}
  10. {*                                                       *}
  11. {*                                                       *}
  12. {*                 All rights reserved.                  *}
  13. {*********************************************************}
  14.  
  15. unit TPWrdStr;
  16.   {-Routines to support strings which use a word in the place of Turbo Pascal's
  17.     byte for holding the length of a string -- theoretically allowing strings
  18.     as large as 64k.}
  19.  
  20. interface
  21.  
  22. uses
  23.   TpString;
  24.  
  25. const
  26.   MaxWrdStr = 1024;          {Maximum length of WrdStr - increase up to 65519}
  27.   NotFound = 0;              {Returned by the Pos functions if substring not found}
  28.  
  29. type
  30.   WrdStr = array[-1..MaxWrdStr] of Char;
  31.   WrdStrPtr = ^WrdStr;
  32.  
  33. function WrdStr2Str(var A : WrdStr) : string;
  34.   {-Convert WrdStr to Turbo string, truncating if longer than 255 chars}
  35.  
  36. procedure Str2WrdStr(S : string; var A : WrdStr);
  37.   {-Convert a Turbo string into an WrdStr}
  38.  
  39. function LenWrdStr(A : WrdStr) : Word;
  40.   {-Return the length of an WrdStr string}
  41.  
  42. procedure CopyWrdStr(var A : WrdStr; Start, Len : Word; var O : WrdStr);
  43.   {-Return a substring of a. Note start=1 for first char in a}
  44.  
  45. procedure DeleteWrdStr(var A : WrdStr; Start, Len : Word);
  46.   {-Delete len characters of a, starting at position start}
  47.  
  48. procedure ConcatWrdStr(var A, B, C : WrdStr);
  49.   {-Concatenate two WrdStr strings, returning a third}
  50.  
  51. procedure ConcatStr(var A : WrdStr; S : string; var C : WrdStr);
  52.   {-Concatenate a string to an WrdStr, returning a new WrdStr}
  53.  
  54. procedure InsertWrdStr(var Obj, A : WrdStr; Start : Word);
  55.   {-Insert WrdStr obj at position start of a}
  56.  
  57. procedure InsertStr(Obj : string; var A : WrdStr; Start : Word);
  58.   {-Insert string obj at position start of a}
  59.  
  60. function PosStr(Obj : string; var A : WrdStr) : Word;
  61.   {-Return the position of the string obj in a, returning NotFound if not found}
  62.  
  63. function PosWrdStr(var Obja, A : WrdStr) : Word;
  64.   {-Return the position of obja in a, returning NotFound if not found}
  65.  
  66. function WrdStrToHeap(var A : WrdStr) : WrdStrPtr;
  67.   {-Put WrdStr on heap, returning a pointer, nil if insufficient memory}
  68.  
  69. procedure WrdStrFromHeap(P : WrdStrPtr; var A : WrdStr);
  70.   {-Return an WrdStr from the heap, empty if pointer is nil}
  71.  
  72. procedure DisposeWrdStr(P : WrdStrPtr);
  73.   {-Dispose of heap space pointed to by P}
  74.  
  75. function ReadLnWrdStr(var F : Text; var A : WrdStr) : Boolean;
  76.   {-Read an WrdStr from text file, returning true if successful}
  77.  
  78. function WriteWrdStr(var F : Text; var A : WrdStr) : Boolean;
  79.   {-Write an WrdStr to text file, returning true if successful}
  80.  
  81. procedure WrdStrUpcase(var A, B : WrdStr);
  82.   {-Uppercase the WrdStr in a, returning b}
  83.  
  84. procedure WrdStrLocase(var A, B : WrdStr);
  85.   {-Lowercase the WrdStr in a, returning b}
  86.  
  87. procedure WrdStrCharStr(Ch : Char; Len : Word; var A : WrdStr);
  88.   {-Return an WrdStr of length len filled with ch}
  89.  
  90. procedure WrdStrPadCh(var A : WrdStr; Ch : Char; Len : Word; var B : WrdStr);
  91.   {-Right-pad the WrdStr in a to length len with ch, returning b}
  92.  
  93. procedure WrdStrPad(var A : WrdStr; Len : Word; var B : WrdStr);
  94.   {-Right-pad the WrdStr in a to length len with blanks, returning b}
  95.  
  96. procedure WrdStrLeftPadCh(var A : WrdStr; Ch : Char; Len : Word; var B : WrdStr);
  97.   {-Left-pad the WrdStr in a to length len with ch, returning b}
  98.  
  99. procedure WrdStrLeftPad(var A : WrdStr; Len : Word; var B : WrdStr);
  100.   {-Left-pad the WrdStr in a to length len with blanks, returning b}
  101.  
  102. procedure WrdStrTrimLead(var A, B : WrdStr);
  103.   {-Return an WrdStr with leading white space removed}
  104.  
  105. procedure WrdStrTrimTrail(var A, B : WrdStr);
  106.   {-Return an WrdStr with trailing white space removed}
  107.  
  108. procedure WrdStrTrim(var A, B : WrdStr);
  109.   {-Return an WrdStr with leading and trailing white space removed}
  110.  
  111. procedure WrdStrCenterCh(var A : WrdStr; Ch : Char; Width : Word; var B : WrdStr);
  112.   {-Return an WrdStr centered in an WrdStr of Ch with specified width}
  113.  
  114. procedure WrdStrCenter(var A : WrdStr; Width : Word; var B : WrdStr);
  115.   {-Return an WrdStr centered in an WrdStr of blanks with specified width}
  116.  
  117. function CompWrdStr(var a1, a2 : WrdStr) : Boolean;
  118.   {-Return equivalence of a1 and a2}
  119.  
  120.   {==========================================================================}
  121.  
  122. implementation
  123. const
  124.  Blank : char = #32;
  125.  
  126.   function WrdStr2Str(var A : WrdStr) : string;
  127.     {-Convert WrdStr to Turbo string, truncating if longer than 255 chars}
  128.   var
  129.     S : string;
  130.     Len : Word absolute A;
  131.     Slen : byte Absolute S;
  132.   begin
  133.     if Len > 255 then SLen := 255
  134.     else Slen := Len;
  135.     Move(A[1], S[1], SLen);
  136.     WrdStr2Str := S;
  137.   end;
  138.  
  139.   procedure Str2WrdStr(S : string; var A : WrdStr);
  140.     {-Convert a Turbo string into an WrdStr}
  141.   var
  142.     slen : byte absolute S;
  143.     alen : word absolute A;
  144.   begin
  145.     Move(S[1], A[1], slen);
  146.     alen := slen;
  147.   end;
  148.  
  149.   function LenWrdStr(A : WrdStr) : Word;
  150.     {-Return the length of an WrdStr string}
  151.   var
  152.     alen : Word absolute A;
  153.   begin
  154.     LenWrdStr := alen;
  155.   end;
  156.  
  157.   procedure CopyWrdStr(var A : WrdStr; Start, Len : Word; var O : WrdStr);
  158.     {-Return a substring of a. Note start=1 for first char in a}
  159.   var
  160.     alen : Word absolute A;
  161.     olen : Word absolute O;
  162.   begin
  163.     if Start > alen then
  164.       Olen := 0
  165.     else begin
  166.       {Don't copy more than exists}
  167.       if Start+Len > alen then
  168.         Len := Succ(alen-Start);
  169.       Move(A[Start], O[1], Len);
  170.       Olen := Len;
  171.     end;
  172.   end;
  173.  
  174.   procedure DeleteWrdStr(var A : WrdStr; Start, Len : Word);
  175.     {-Delete len characters of a, starting at position start}
  176.   var
  177.     alen : Word Absolute A;
  178.     mid : Word;
  179.   begin
  180.     if Start <= alen then begin
  181.       {Don't do anything if start position exceeds length of string}
  182.       mid := Start+Len;
  183.       if mid <= alen then begin
  184.         {Move right remainder of string left}
  185.         Move(A[mid], A[Start], len);
  186.         Dec(alen,len);
  187.       end else
  188.         {Entire end of string deleted}
  189.         alen := Pred(Start);
  190.     end;
  191.   end;
  192.  
  193.   procedure ConcatWrdStr(var A, B, C : WrdStr);
  194.     {-Concatenate two WrdStr strings, returning a third}
  195.   var
  196.     alen : Word absolute A;
  197.     blen : Word absolute B;
  198.     clen : Word absolute C;
  199.     temp : Word;
  200.   begin
  201.  
  202.     {Put a into the result}
  203.     Move(A[1], C[1], alen);
  204.  
  205.     {Store as much of b as fits into result}
  206.     Temp := blen;
  207.     if alen+blen > MaxWrdStr then
  208.       Temp := MaxWrdStr-alen;
  209.     Move(B[1], C[Succ(alen)], Temp);
  210.  
  211.     {Terminate the result}
  212.     clen := alen+blen;
  213.   end;
  214.  
  215.   procedure ConcatStr(var A : WrdStr; S : string; var C : WrdStr);
  216.     {-Concatenate a string to an WrdStr, returning a new WrdStr}
  217.   var
  218.     alen : Word absolute A;
  219.     clen : Word absolute C;
  220.     slen : Byte absolute S;
  221.   begin
  222.  
  223.     {Put a into the result}
  224.     Move(A[1], C[1], alen);
  225.  
  226.     {Store as much of s as fits into result}
  227.     if alen+slen > MaxWrdStr then
  228.       slen := MaxWrdStr-alen;
  229.     Move(S[1], C[succ(alen)], slen);
  230.  
  231.     {Terminate the result}
  232.     clen := alen+slen;
  233.   end;
  234.  
  235.   procedure InsertWrdStr(var Obj, A : WrdStr; Start : Word);
  236.     {-Insert WrdStr obj at position start of a}
  237.   var
  238.     alen : Word absolute A;
  239.     olen : Word absolute Obj;
  240.     mid, temp : Word;
  241.   begin
  242.  
  243.     if Start > alen then
  244.       {Concatenate if start exceeds alen}
  245.       Start := Succ(alen)
  246.  
  247.     else begin
  248.       {Move right side characters right to make space for insert}
  249.       mid := Start+olen;
  250.       if mid <= MaxWrdStr then
  251.         {Room for at least some of the right side characters}
  252.         if alen+olen <= MaxWrdStr then
  253.           {Room for all of the right side}
  254.           Move(A[Start], A[mid], Succ(alen-Start))
  255.         else
  256.           {Room for part of the right side}
  257.           Move(A[Start], A[mid], Succ(MaxWrdStr-mid));
  258.     end;
  259.  
  260.     {Insert the obj string}
  261.     temp := Olen;
  262.     if Start+olen > MaxWrdStr then
  263.       temp := Succ(MaxWrdStr-Start);
  264.     Move(Obj[1], A[Start], temp);
  265.  
  266.     {Terminate the string}
  267.     if alen+olen <= MaxWrdStr then
  268.       Inc(alen,olen)
  269.     else
  270.       alen := MaxWrdStr;
  271.   end;
  272.  
  273.   procedure InsertStr(Obj : string; var A : WrdStr; Start : Word);
  274.     {-Insert string obj at position start of a}
  275.   var
  276.     alen : Word absolute A;
  277.     olen : byte absolute Obj;
  278.     mid,temp : Word;
  279.   begin
  280.  
  281.     if Start > alen then
  282.       {Concatenate if start exceeds alen}
  283.       Start := succ(alen)
  284.  
  285.     else begin
  286.       {Move right side characters right to make space for insert}
  287.       mid := Start+olen;
  288.       if mid <= MaxWrdStr then
  289.         {Room for at least some of the right side characters}
  290.         if alen+olen <= MaxWrdStr then
  291.           {Room for all of the right side}
  292.           Move(A[Start], A[mid], Succ(alen-Start))
  293.         else
  294.           {Room for part of the right side}
  295.           Move(A[Start], A[mid], Succ(MaxWrdStr-mid));
  296.     end;
  297.  
  298.     {Insert the obj string}
  299.     temp := olen;
  300.     if Start+olen > MaxWrdStr then
  301.       temp := Succ(MaxWrdStr-Start);
  302.     Move(Obj[1], A[Start], temp);
  303.  
  304.     {Terminate the string}
  305.     if alen+olen <= MaxWrdStr then
  306.       Inc(alen,olen)
  307.     else
  308.       alen := MaxWrdStr;
  309.   end;
  310.  
  311.   {$L TPWrdStr}
  312.   function Search(var Buffer; BufLength : Word; var Match; MatLength : Word) : Word;
  313.     external;
  314.   procedure WrdStrUpcase(var A, B : WrdStr);
  315.     {-Upper case WrdStr A, returning it in B}
  316.   var
  317.     alen : Word absolute A;
  318.     x : Word;
  319.   begin
  320.     For x:=1 to alen do A[x]:=UpCase(A[x]);
  321.     Move(A,B,alen+2);
  322.   end;
  323.   procedure WrdStrLocase(var A, B : WrdStr);
  324.     {-Lower case WrdStr A, returning it in B}
  325.   var
  326.     alen : Word absolute A;
  327.     x : Word;
  328.   begin
  329.     For x:=1 to alen do A[x]:=LoCase(A[x]);
  330.     Move(A,B,alen+2);
  331.   end;
  332.  
  333.   function CompWrdStr(var a1, a2 : WrdStr) : Boolean;
  334.     {-Compare WrdStr's a1 and a2 and return equivalence}
  335.   var
  336.    alen1 : Word absolute A1;
  337.    alen2 : Word absolute A2;
  338.    x : Word;
  339.   begin
  340.     CompWrdStr := false;
  341.     If (alen1=alen2) then  {possibly equal, let's check it out}
  342.     begin
  343.       for x:=1 to alen1 do if (A1[x]<>A2[x]) then exit;
  344.       CompWrdStr := true;  {If we made it to here, they must be equal}
  345.     end;
  346.   end;
  347.  
  348.   function PosStr(Obj : string; var A : WrdStr) : Word;
  349.     {-Return the position of the string obj in a, returning NotFound if not found}
  350.   var
  351.     alen : Word absolute A;
  352.     olen : Byte absolute Obj;
  353.     PosFound : Word;
  354.   begin
  355.     PosFound := Search(A[1], alen, Obj[1], olen);
  356.     If (PosFound = $FFFF) then {Search didn't find it}
  357.        PosFound := 0;
  358.     PosStr := Succ(PosFound);
  359.   end;
  360.  
  361.   function PosWrdStr(var Obja, A : WrdStr) : Word;
  362.     {-Return the position of obja in a, returning NotFound if not found}
  363.   var
  364.     alen : Word absolute A;
  365.     olen : Word absolute Obja;
  366.     PosFound : Word;
  367.   begin
  368.     PosFound := Search(A[1], alen, Obja[1], olen);
  369.     If (PosFound = $FFFF) then {Search didn't find it}
  370.        PosFound := 0;
  371.     PosWrdStr := Succ(PosFound);
  372.   end;
  373.  
  374.   function WrdStrToHeap(var A : WrdStr) : WrdStrPtr;
  375.     {-Put WrdStr on heap, returning a pointer, nil if insufficient memory}
  376.   var
  377.     alen : Word;
  378.     P : WrdStrPtr;
  379.   begin
  380.     alen := LenWrdStr(A)+2;
  381.     if MaxAvail >= alen then begin
  382.       GetMem(P, alen);
  383.       Move(A, P^, alen);
  384.       WrdStrToHeap := P;
  385.     end else
  386.       WrdStrToHeap := nil;
  387.   end;
  388.  
  389.   procedure WrdStrFromHeap(P : WrdStrPtr; var A : WrdStr);
  390.     {-Return an WrdStr from the heap, empty if pointer is nil}
  391.   var
  392.     alen : Word absolute a;
  393.     plen : Word absolute p;
  394.   begin
  395.     if P = nil then
  396.       Alen := 0
  397.     else
  398.       Move(P^, A, Plen+2);
  399.   end;
  400.  
  401.   procedure DisposeWrdStr(P : WrdStrPtr);
  402.     {-Dispose of heap space pointed to by P}
  403.   begin
  404.     if P <> nil then
  405.       FreeMem(P, LenWrdStr(P^)+2);
  406.   end;
  407.  
  408.   procedure WrdStrCharStr(Ch : Char; Len : Word; var A : WrdStr);
  409.     {-Return an WrdStr of length len filled with ch}
  410.   var
  411.     alen : Word absolute A;
  412.   begin
  413.     if Len = 0 then
  414.       Alen := 0
  415.     else begin
  416.       if Len > MaxWrdStr then
  417.         Len := MaxWrdStr;
  418.       FillChar(A[1], Len, Ch);
  419.       Alen := Len;
  420.     end;
  421.   end;
  422.  
  423.   procedure WrdStrPadCh(var A : WrdStr; Ch : Char; Len : Word; var B : WrdStr);
  424.     {-Right-pad the WrdStr to length len with ch, returning b}
  425.   var
  426.     alen : Word Absolute A;
  427.     blen : Word Absolute B;
  428.   begin
  429.     if alen >= Len then
  430.       {Return the input string}
  431.       Move(A, B, alen+2)
  432.     else begin
  433.       if Len > MaxWrdStr then
  434.         Len := MaxWrdStr;
  435.       Move(A[1], B[1], alen);
  436.       FillChar(B[succ(alen)], Len-alen, Ch);
  437.       Blen := len;
  438.     end;
  439.   end;
  440.  
  441.   procedure WrdStrPad(var A : WrdStr; Len : Word; var B : WrdStr);
  442.     {-Right-pad the WrdStr to length len with blanks, returning b}
  443.   begin
  444.     WrdStrPadCh(A, Blank, Len, B);
  445.   end;
  446.  
  447.   procedure WrdStrLeftPadCh(var A : WrdStr; Ch : Char; Len : Word; var B : WrdStr);
  448.     {-Left-pad the WrdStr in a to length len with ch, returning b}
  449.   var
  450.     alen : Word absolute A;
  451.     blen : Word absolute B;
  452.   begin
  453.     if alen >= Len then
  454.       {Return the input string}
  455.       Move(A, B, alen+2)
  456.     else begin
  457.       FillChar(B[1], Len-alen, Ch);
  458.       Move(A[1], B[Succ(Len-alen)], alen);
  459.       BLen := Len;
  460.     end;
  461.   end;
  462.  
  463.   procedure WrdStrLeftPad(var A : WrdStr; Len : Word; var B : WrdStr);
  464.     {-Left-pad the WrdStr in a to length len with blanks, returning b}
  465.   begin
  466.     WrdStrLeftPadCh(A, Blank, Len, B);
  467.   end;
  468.  
  469.   procedure WrdStrTrimLead(var A, B : WrdStr);
  470.     {-Return an WrdStr with leading white space removed}
  471.   var
  472.     alen : Word absolute A;
  473.     apos : Word;
  474.   begin
  475.     apos := 1;
  476.     while (apos < alen) and (A[apos] <= Blank) do
  477.       Inc(apos);
  478.     Move(A[apos], B[1], Succ(alen-apos));
  479.   end;
  480.  
  481.   procedure WrdStrTrimTrail(var A, B : WrdStr);
  482.     {-Return an WrdStr with trailing white space removed}
  483.   var
  484.     alen : Word absolute A;
  485.     blen : Word absolute B;
  486.   begin
  487.     while (alen > 1) and (A[Pred(alen)] <= Blank) do
  488.       Dec(alen);
  489.     Move(A, B, alen+2);
  490.   end;
  491.  
  492.   procedure WrdStrTrim(var A, B : WrdStr);
  493.     {-Return an WrdStr with leading and trailing white space removed}
  494.   var
  495.     blen : Word Absolute B;
  496.   begin
  497.     WrdStrTrimLead(A, B);
  498.     while (blen > 1) and (B[Pred(blen)] <= Blank) do
  499.       Dec(blen);
  500.   end;
  501.  
  502.   procedure WrdStrCenterCh(var A : WrdStr; Ch : Char; Width : Word; var B : WrdStr);
  503.     {-Return an WrdStr centered in an WrdStr of Ch with specified width}
  504.   var
  505.     alen : Word absolute A;
  506.     blen : Word absolute B;
  507.   begin
  508.     if alen >= Width then
  509.       {Return input}
  510.       Move(A, B, alen+2)
  511.     else begin
  512.       FillChar(B[1], Width, Ch);
  513.       Move(A[1], B[Succ((Width-alen) shr 1)], alen);
  514.       Blen := Width;
  515.     end;
  516.   end;
  517.  
  518.   procedure WrdStrCenter(var A : WrdStr; Width : Word; var B : WrdStr);
  519.     {-Return an WrdStr centered in an WrdStr of blanks with specified width}
  520.   begin
  521.     WrdStrCenterCh(A, Blank, Width, B);
  522.   end;
  523.  
  524. type
  525.   {text buffer}
  526.   TextBuffer = array[0..65520] of Byte;
  527.  
  528.   {structure of a Turbo File Interface Block}
  529.   FIB = record
  530.           Handle : Word;
  531.           Mode : Word;
  532.           BufSize : Word;
  533.           Private : Word;
  534.           BufPos : Word;
  535.           BufEnd : Word;
  536.           BufPtr : ^TextBuffer;
  537.           OpenProc : Pointer;
  538.           InOutProc : Pointer;
  539.           FlushProc : Pointer;
  540.           CloseProc : Pointer;
  541.           UserData : array[1..16] of Byte;
  542.           Name : array[0..79] of Char;
  543.           Buffer : array[0..127] of Char;
  544.         end;
  545.  
  546. const
  547.   FMClosed = $D7B0;
  548.   FMInput = $D7B1;
  549.   FMOutput = $D7B2;
  550.   FMInOut = $D7B3;
  551.   CR : Char = ^M;
  552.  
  553.   function ReadLnWrdStr(var F : Text; var A : WrdStr) : Boolean;
  554.     {-Read an WrdStr from text file, returning true if successful}
  555.   var
  556.     CrPos : Word;
  557.     alen : Word absolute A;
  558.     blen : Word;
  559.  
  560.     function RefillBuf(var F : Text) : Boolean;
  561.       {-Refill buffer}
  562.     var
  563.       Ch : Char;
  564.     begin
  565.       with FIB(F) do begin
  566.         BufEnd := 0;
  567.         BufPos := 0;
  568.         Read(F, Ch);
  569.         if IoResult <> 0 then begin
  570.           {Couldn't read from file}
  571.           RefillBuf := False;
  572.           Exit;
  573.         end;
  574.         {Reset the buffer again}
  575.         BufPos := 0;
  576.         RefillBuf := True;
  577.       end;
  578.     end;
  579.  
  580.  
  581.   begin
  582.     with FIB(F) do begin
  583.  
  584.       {Initialize the WrdStr length and function result}
  585.       alen := 0;
  586.       ReadLnWrdStr := False;
  587.  
  588.       {Make sure file open for input}
  589.       if Mode <> FMInput then
  590.         Exit;
  591.  
  592.       {Make sure something is in buffer}
  593.       if BufPos >= BufEnd then
  594.         if not(RefillBuf(F)) then
  595.           Exit;
  596.  
  597.       {Use the Turbo text file buffer to build the WrdStr}
  598.       repeat
  599.  
  600.         {Search for the next carriage return in the file buffer}
  601.         CrPos := Search(BufPtr^[BufPos], Succ(BufEnd-BufPos), CR, 1);
  602.  
  603.         if CrPos = $FFFF then begin
  604.           {CR not found, save the portion of the buffer seen so far}
  605.           blen := BufEnd-BufPos;
  606.           if alen+blen > MaxWrdStr then
  607.             blen := MaxWrdStr-alen;
  608.  
  609.           Move(BufPtr^[BufPos], A[alen], blen);
  610.           Inc(alen, blen);
  611.  
  612.           {See if at end of file}
  613.           if eof(F) then begin
  614.             {Force exit with this line}
  615.             CrPos := 0;
  616.             {Remove trailing ^Z}
  617.             while (alen > 1) and (A[Pred(alen)] = ^Z) do
  618.               Dec(alen);
  619.           end else if not(RefillBuf(F)) then
  620.             Exit;
  621.  
  622.         end else begin
  623.           {Save up to the CR}
  624.           blen := CrPos;
  625.           if alen+blen > MaxWrdStr then
  626.             blen := MaxWrdStr-alen;
  627.           Move(BufPtr^[BufPos], A[alen], blen);
  628.           Inc(alen, blen);
  629.  
  630.           {Inform Turbo we used the characters}
  631.           Inc(BufPos, Succ(CrPos));
  632.  
  633.           {Skip over following ^J}
  634.           if BufPos < BufEnd then begin
  635.             {Next character is within current buffer}
  636.             if BufPtr^[BufPos] = Ord(^J) then
  637.               Inc(BufPos);
  638.           end else begin
  639.             {Next character is not within current buffer}
  640.             {Refill the buffer}
  641.             if not(RefillBuf(F)) then
  642.               Exit;
  643.             if BufPos < BufEnd then
  644.               if BufPtr^[BufPos] = Ord(^J) then
  645.                 Inc(BufPos);
  646.           end;
  647.  
  648.         end;
  649.  
  650.       until (CrPos <> $FFFF) or (alen > MaxWrdStr);
  651.  
  652.       {Return success and terminate the WrdStr}
  653.       ReadLnWrdStr := True;
  654.  
  655.     end;
  656.   end;
  657.  
  658.   function WriteWrdStr(var F : Text; var A : WrdStr) : Boolean;
  659.     {-Write an WrdStr to text file, returning true if successful}
  660.   var
  661.     S : string;
  662.     alen : Word absolute A;
  663.     apos : Word;
  664.     slen : Byte absolute S;
  665.   begin
  666.     apos := 1;
  667.     WriteWrdStr := False;
  668.  
  669.     {Write the WrdStr as a series of strings}
  670.     while apos < alen do begin
  671.       slen := alen-apos;
  672.       if slen > 255 then
  673.         slen := 255;
  674.       Move(A[apos], S[1], slen);
  675.       Write(F, S);
  676.       if IoResult <> 0 then
  677.         Exit;
  678.       Inc(apos, slen);
  679.     end;
  680.  
  681.     WriteWrdStr := True;
  682.   end;
  683.  
  684. end.
  685.